﻿namespace Guru.Framework.Util
{
    using System;
    using System.Text;

    public class SecurityUtil
    {
        internal static string EncodeString(string data)
        {
            try
            {
                if (string.IsNullOrEmpty(data) == false)
                {
                    string encodedData = Encode(data);
                    Random rnd = new Random();
                    int shiftCount = rnd.Next(1, encodedData.Length);
                    string shifted = ShiftAString(encodedData, shiftCount);
                    return Encode(string.Concat(shifted, Convert.ToChar(shiftCount)));
                }
                else
                    return string.Empty;

            }
            catch (Exception)
            {
                throw;
            }
        }

        internal static string DecodeString(string data)
        {
            try
            {
                if (string.IsNullOrEmpty(data) == false)
                {
                    string firstDecode = Decode(data);
                    int unshiftCount = ConverterUtil.Convert2Int(firstDecode[firstDecode.Length - 1]);
                    firstDecode = firstDecode.Substring(0, firstDecode.Length - 1);
                    firstDecode = UnShiftString(firstDecode, unshiftCount);
                    string lastDecode = Decode(firstDecode);
                    return lastDecode;
                }
                else
                    return string.Empty;
            }
            catch (Exception)
            {
                throw;
            }
        }

        public static string Decode(string data)
        {
            try
            {
                System.Text.UTF8Encoding encoder = new System.Text.UTF8Encoding();
                System.Text.Decoder utf8Decode = encoder.GetDecoder();

                byte[] todecode_byte = Convert.FromBase64String(data);
                int charCount = utf8Decode.GetCharCount(todecode_byte, 0, todecode_byte.Length);
                char[] decoded_char = new char[charCount];
                utf8Decode.GetChars(todecode_byte, 0, todecode_byte.Length, decoded_char, 0);
                string result = new String(decoded_char);
                return result;
            }
            catch (Exception)
            {
                throw;
            }
        }

        public static string Encode(string data)
        {
            try
            {
                byte[] encData_byte = new byte[data.Length];
                encData_byte = System.Text.Encoding.UTF8.GetBytes(data);
                string encodedData = Convert.ToBase64String(encData_byte);
                return encodedData;
            }
            catch (Exception)
            {
                throw;
            }
        }

        static string ShiftAString(string shifted, int shiftCount)
        {
            try
            {
                if (string.IsNullOrEmpty(shifted) == false)
                {
                    int lenStr = shifted.Length;
                    StringBuilder strBuilder = new StringBuilder();
                    for (int lenCounter = 0; lenCounter < lenStr; lenCounter++)
                    {
                        strBuilder.Append(shifted[(lenCounter + shiftCount) % lenStr]);
                    }
                    return strBuilder.ToString();
                }
                else
                {
                    return string.Empty;
                }
            }
            catch (Exception)
            {
                throw;
            }
        }

        static string UnShiftString(string unshifted, int unshiftCount)
        {
            try
            {
                if (string.IsNullOrEmpty(unshifted) == false)
                {
                    int lenStr = unshifted.Length;
                    StringBuilder strBuilder = new StringBuilder();
                    for (int lenCounter = 0; lenCounter < lenStr; lenCounter++)
                    {
                        strBuilder.Append(unshifted[(lenCounter + lenStr - unshiftCount) % lenStr]);
                    }
                    return strBuilder.ToString();
                }
                else
                {
                    return string.Empty;
                }
            }
            catch (Exception)
            {
                throw;
            }
        }
    }
}
